/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.grails.data.testing.tck.tests

import spock.lang.Issue

import org.apache.grails.data.testing.tck.base.GrailsDataTckSpec
import org.apache.grails.data.testing.tck.domains.EnumThing
import org.apache.grails.data.testing.tck.domains.TestEnum

class EnumSpec extends GrailsDataTckSpec {

    void "Test save()"() {
        given:

        EnumThing t = new EnumThing(name: 'e1', en: TestEnum.V1)

        when:
        t.save(failOnError: true, flush: true)

        then:
        t != null
        !t.hasErrors()

        when:
        t = t.get(t.id)

        then:
        t != null
        'e1' == t.name
        TestEnum.V1 == t.en
    }

    @Issue('GPMONGODB-248')
    void "Test findByInList()"() {
        given:

        new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true)

        EnumThing instance1
        EnumThing instance2
        EnumThing instance3

        when:
        instance1 = EnumThing.findByEnInList([TestEnum.V1])
        instance2 = EnumThing.findByEnInList([TestEnum.V2])
        instance3 = EnumThing.findByEnInList([TestEnum.V3])

        then:
        instance1 != null
        instance1.en == TestEnum.V1

        instance2 != null
        instance2.en == TestEnum.V2

        instance3 == null
    }

    void "Test findBy()"() {
        given:

        new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true)

        EnumThing instance1
        EnumThing instance2
        EnumThing instance3

        when:
        instance1 = EnumThing.findByEn(TestEnum.V1)
        instance2 = EnumThing.findByEn(TestEnum.V2)
        instance3 = EnumThing.findByEn(TestEnum.V3)

        then:
        instance1 != null
        instance1.en == TestEnum.V1

        instance2 != null
        instance2.en == TestEnum.V2

        instance3 == null
    }

    void "Test findBy() with clearing the session"() {
        given:

        new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true, flush: true)
        new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true, flush: true)
        new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true, flush: true)
        manager.session.clear()

        EnumThing instance1
        EnumThing instance2
        EnumThing instance3

        when:
        instance1 = EnumThing.findByEn(TestEnum.V1)
        instance2 = EnumThing.findByEn(TestEnum.V2)
        instance3 = EnumThing.findByEn(TestEnum.V3)

        then:
        instance1 != null
        instance1.en == TestEnum.V1

        instance2 != null
        instance2.en == TestEnum.V2

        instance3 == null
    }

    void "Test findAllBy()"() {
        given:

        new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true)

        def v1Instances
        def v2Instances
        def v3Instances
        def v12Instances

        when:
        v1Instances = EnumThing.findAllByEn(TestEnum.V1)
        v2Instances = EnumThing.findAllByEn(TestEnum.V2)
        v3Instances = EnumThing.findAllByEn(TestEnum.V3)
        v12Instances = EnumThing.findAllByEnInList([TestEnum.V1, TestEnum.V2])

        then:
        v1Instances != null
        v1Instances.size() == 2
        v1Instances.every { it.en == TestEnum.V1 }

        v2Instances != null
        v2Instances.size() == 1
        v2Instances.every { it.en == TestEnum.V2 }

        v3Instances != null
        v3Instances.isEmpty()

        v12Instances != null
        v12Instances.size() == 3
    }

    void "Test countBy()"() {
        given:

        new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true)
        new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true)

        def v1Count
        def v2Count
        def v3Count

        when:
        v1Count = EnumThing.countByEn(TestEnum.V1)
        v2Count = EnumThing.countByEn(TestEnum.V2)
        v3Count = EnumThing.countByEn(TestEnum.V3)

        then:
        2 == v1Count
        1 == v2Count
        0 == v3Count
    }
}
